<?php
namespace App\Models;

use App\Config\Database;
use PDO;
use PDOException;

/**
 * 群消息已读状态模型
 * @package App\Models
 * @description:
 * 1. 标记消息为已读
 * 2. 检查消息是否已读
 * 3. 获取用户在群组中的已读消息
 * 4. 获取消息的已读用户列表
 * 5. 获取群组中未读消息数量
 */
class MessageRead {
    private $conn;
    private $table = 'message_reads';

    public $id;
    public $message_id;
    public $group_id;
    public $user_id;
    public $read_at;

    public function __construct() {
        $database = new Database();
        $this->conn = $database->getConnection();
    }

    /**
     * 标记消息为已读
     * @param string $messageId 消息ID
     * @param int $userId 用户ID
     * @param int $groupId 群组ID
     * @return bool
     */
    public function markAsRead($messageId, $userId, $groupId) {
        try {
            // 先检查是否已经标记过
            $checkQuery = "SELECT COUNT(*) as count 
                           FROM " . $this->table . " 
                           WHERE message_id = :message_id AND user_id = :user_id";
            $checkStmt = $this->conn->prepare($checkQuery);
            $checkStmt->bindParam(':message_id', $messageId);
            $checkStmt->bindParam(':user_id', $userId);
            $checkStmt->execute();
            $result = $checkStmt->fetch(PDO::FETCH_ASSOC);
            
            if ($result['count'] > 0) {
                return true; // 已标记过，直接返回成功
            }
            
            // 插入新记录
            $insertQuery = "INSERT INTO " . $this->table . " 
                           (message_id, group_id, user_id) 
                           VALUES (:message_id, :group_id, :user_id)";
            $insertStmt = $this->conn->prepare($insertQuery);
            $insertStmt->bindParam(':message_id', $messageId);
            $insertStmt->bindParam(':group_id', $groupId);
            $insertStmt->bindParam(':user_id', $userId);
            
            return $insertStmt->execute();
        } catch (PDOException $e) {
            error_log("Mark message as read error: " . $e->getMessage());
            return false;
        }
    }

    /**
     * 检查消息是否已读
     * @param string $messageId 消息ID
     * @param int $userId 用户ID
     * @return bool
     */
    public function isRead($messageId, $userId) {
        try {
            $query = "SELECT COUNT(*) as count 
                      FROM " . $this->table . " 
                      WHERE message_id = :message_id AND user_id = :user_id";
            $stmt = $this->conn->prepare($query);
            $stmt->bindParam(':message_id', $messageId);
            $stmt->bindParam(':user_id', $userId);
            $stmt->execute();
            
            $result = $stmt->fetch(PDO::FETCH_ASSOC);
            return $result['count'] > 0;
        } catch (PDOException $e) {
            error_log("Check if message is read error: " . $e->getMessage());
            return false;
        }
    }

    /**
     * 获取用户在群组中的已读消息ID列表
     * @param int $userId 用户ID
     * @param int $groupId 群组ID
     * @return array
     */
    public function getReadMessagesForUser($userId, $groupId) {
        try {
            $query = "SELECT message_id 
                      FROM " . $this->table . " 
                      WHERE user_id = :user_id AND group_id = :group_id";
            $stmt = $this->conn->prepare($query);
            $stmt->bindParam(':user_id', $userId);
            $stmt->bindParam(':group_id', $groupId);
            $stmt->execute();
            
            $result = $stmt->fetchAll(PDO::FETCH_ASSOC);
            return array_column($result, 'message_id');
        } catch (PDOException $e) {
            error_log("Get read messages for user error: " . $e->getMessage());
            return [];
        }
    }

    /**
     * 获取消息的已读用户列表
     * @param string $messageId 消息ID
     * @return array
     */
    public function getReadUsersForMessage($messageId) {
        try {
            $query = "SELECT user_id 
                      FROM " . $this->table . " 
                      WHERE message_id = :message_id";
            $stmt = $this->conn->prepare($query);
            $stmt->bindParam(':message_id', $messageId);
            $stmt->execute();
            
            $result = $stmt->fetchAll(PDO::FETCH_ASSOC);
            return array_column($result, 'user_id');
        } catch (PDOException $e) {
            error_log("Get read users for message error: " . $e->getMessage());
            return [];
        }
    }

    /**
     * 获取群组中用户的未读消息数量
     * @param int $userId 用户ID
     * @param int $groupId 群组ID
     * @return int
     */
    public function getUnreadCountForGroup($userId, $groupId) {
        try {
            // 获取群组最后一条消息的时间戳
            $lastMessageQuery = "SELECT MAX(timestamp) as last_timestamp 
                                FROM messages 
                                WHERE receiver_type = 2 AND receiver_id = :group_id";
            $lastMessageStmt = $this->conn->prepare($lastMessageQuery);
            $lastMessageStmt->bindParam(':group_id', $groupId);
            $lastMessageStmt->execute();
            $lastMessage = $lastMessageStmt->fetch(PDO::FETCH_ASSOC);
            
            if (!$lastMessage || !$lastMessage['last_timestamp']) {
                return 0;
            }
            
            // 获取用户最后已读消息的时间戳
            $lastReadQuery = "SELECT MAX(m.timestamp) as last_read_timestamp
                             FROM " . $this->table . " mr
                             JOIN messages m ON mr.message_id = m.message_id
                             WHERE mr.user_id = :user_id AND mr.group_id = :group_id";
            $lastReadStmt = $this->conn->prepare($lastReadQuery);
            $lastReadStmt->bindParam(':user_id', $userId);
            $lastReadStmt->bindParam(':group_id', $groupId);
            $lastReadStmt->execute();
            $lastRead = $lastReadStmt->fetch(PDO::FETCH_ASSOC);
            
            // 计算未读消息数量
            $whereClause = "WHERE receiver_type = 2 AND receiver_id = :group_id";
            $params = [':group_id' => $groupId];
            
            if ($lastRead && $lastRead['last_read_timestamp']) {
                $whereClause .= " AND timestamp > :last_read_timestamp";
                $params[':last_read_timestamp'] = $lastRead['last_read_timestamp'];
            }
            
            $countQuery = "SELECT COUNT(*) as count 
                          FROM messages " . $whereClause;
            $countStmt = $this->conn->prepare($countQuery);
            
            foreach ($params as $key => $value) {
                $countStmt->bindValue($key, $value);
            }
            
            $countStmt->execute();
            $result = $countStmt->fetch(PDO::FETCH_ASSOC);
            
            return (int)$result['count'];
        } catch (PDOException $e) {
            error_log("Get unread count for group error: " . $e->getMessage());
            return 0;
        }
    }

    /**
     * 批量标记消息为已读
     * @param array $messageIds 消息ID数组
     * @param int $userId 用户ID
     * @param int $groupId 群组ID
     * @return bool
     */
    public function batchMarkAsRead($messageIds, $userId, $groupId) {
        try {
            $this->conn->beginTransaction();
            
            foreach ($messageIds as $messageId) {
                $this->markAsRead($messageId, $userId, $groupId);
            }
            
            $this->conn->commit();
            return true;
        } catch (PDOException $e) {
            $this->conn->rollBack();
            error_log("Batch mark as read error: " . $e->getMessage());
            return false;
        }
    }

    /**
     * 获取群组中所有未读消息
     * @param int $userId 用户ID
     * @param int $groupId 群组ID
     * @param int $lastReadTimestamp 最后已读时间戳
     * @return array
     */
    public function getUnreadMessagesForGroup($userId, $groupId, $lastReadTimestamp = null) {
        try {
            $query = "SELECT m.* 
                      FROM messages m
                      LEFT JOIN " . $this->table . " mr 
                          ON m.message_id = mr.message_id AND mr.user_id = :user_id
                      WHERE m.receiver_type = 2 
                          AND m.receiver_id = :group_id
                          AND mr.id IS NULL
                          AND m.status = 1";
            
            if ($lastReadTimestamp) {
                $query .= " AND m.timestamp > :last_read_timestamp";
            }
            
            $query .= " ORDER BY m.timestamp ASC";
            
            $stmt = $this->conn->prepare($query);
            $stmt->bindParam(':user_id', $userId);
            $stmt->bindParam(':group_id', $groupId);
            
            if ($lastReadTimestamp) {
                $stmt->bindParam(':last_read_timestamp', $lastReadTimestamp);
            }
            
            $stmt->execute();
            return $stmt->fetchAll(PDO::FETCH_ASSOC);
        } catch (PDOException $e) {
            error_log("Get unread messages for group error: " . $e->getMessage());
            return [];
        }
    }
}